import { camera, scene } from '../utils/init'
import * as THREE from 'three'
// import guiMove from '../utils/gui'
import { CSS3DObject } from 'three/examples/jsm/Addons.js'
// 设置为组 方便一次性清空 方便管理
const group = new THREE.Group()
const sceneInfoObj = {
  one: {
    publicPath: 'technology/1/',
    imgUrlArr: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    markList: [
      {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05], //平面的宽高
        position: [-0.46, -0.11, -0.11],//位置
        rotation: [1.42, 0.68, 1.63],//旋转值
        targetAttr: 'two'//下一个场景数据兑现过的属性名
      }
    ]
  },
  two: {
    publicPath: 'technology/2/',
    imgUrlArr: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    markList: [
      {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05],
        position: [0.47, -0.2, 0],
        rotation: [1.48, 0.26, -1.78],
        targetAttr: 'one' // 目标场景信息对象属性
      }, {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05],
        position: [-0.46, -0.16, -0.3],
        rotation: [1.21, 0.78, 0],
        targetAttr: 'three' // 目标场景信息对象属性
      }
    ]
  },
  three: {
    publicPath: 'technology/3/',
    imgUrlArr: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    markList: [
      {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05],
        position: [0.4, -0.18, 0.32],
        rotation: [-1.53, -0.04, -1.26],
        targetAttr: 'two' // 目标场景信息对象属性
      }, {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05],
        position: [0.32, -0.16, -0.33],
        rotation: [1.46, 0.1, -0.17],
        targetAttr: 'four' // 目标场景信息对象属性
      }
    ]
  },
  four: {
    publicPath: 'technology/4/',
    imgUrlArr: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    markList: [
      {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.05, 0.05],
        position: [-0.35, -0.22, 0.4],
        rotation: [-0.85, -0.45, -1.8],
        targetAttr: 'three' // 目标场景信息对象属性
      },
      {
        name: 'dom',
        position: [0.49, 0, 0],
        rotation: [0, -0.5 * Math.PI, 0],
        targetAttr: 'five', // 目标场景信息对象属性
        active(e) {
          setMaterialCube(sceneInfoObj.five)
        }
      }
    ]
  },
  five: {
    publicPath: 'technology/5/',
    imgUrlArr: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    markList: [
      {
        name: 'landMark',
        imgUrl: 'other/landmark.png',
        wh: [0.03, 0.03],
        position: [-0.05, -0.05, 0.4],
        rotation: [1.21, -0.15, -0.69],
        targetAttr: 'four' // 目标场景信息对象属性
      },
      {
        name: 'video',
        imgUrl: 'video/movie.mp4',
        wh: [0.2, 0.1],
        position: [0.49, 0.04, 0.045],
        rotation: [0, -0.5 * Math.PI, 0]
      }
    ]
  }
}

function clear() {
  const list = [...group.children]
  list.forEach(obj => {
    // 判断是不是dom元素 dom没用材质 材料 没有办法使用dispose方法
    if (!obj.isCSS3DObject) {
      obj.geometry.dispose()
      obj.material.dispose()
    }
    group.remove(obj)
  })
}

function createCube() {
  const geometry = new THREE.BoxGeometry(1, 1, 1)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide })
  const cube = new THREE.Mesh(geometry, material)
  // z轴需要反向翻转！
  cube.scale.set(1, 1, -1)
  scene.add(cube)
  return cube
}

function setMaterialCube(infoObj) {
  clear()//清除上个场景中的标记
  const { publicPath, imgUrlArr, markList } = infoObj
  const textureLoader = new THREE.TextureLoader()
  textureLoader.setPath(publicPath)

  // 遍历纹理图片=>映射纹理对象=> 贴到立方体上
  const materialArr = imgUrlArr.map(i => {
    const texture = textureLoader.load(i)
    texture.colorSpace = THREE.SRGBColorSpace
    return new THREE.MeshBasicMaterial({
      map: texture,
      side: THREE.DoubleSide,
    })
  })
  cubeObj.material = materialArr

  markList.forEach(i => {
    // 如果是地上的热点标记，就调用对应函数传递标记信息对象
    if (i.name === 'landMark') {
      return createLandMark(i)
    } else if (i.name === 'dom') {
      return createDomMark(i)
    } else if (i.name === 'video') {
      return createVideoMark(i)
    }
  })
  scene.add(group)
}

function createDomMark(info) {
  const { position, rotation, active } = info
  const tag = document.createElement('span')
  tag.className = 'mark-style'
  tag.innerHTML = '前进'
  tag.style.pointerEvents = 'all'

  // dom点击事件
  tag.addEventListener('click', (e) => {
    // 为了保证这个函数通用 回调数据对象中的函数代码
    active(e)
  })
  // DOM转换层3D
  const tag3d = new CSS3DObject(tag)
  tag3d.scale.set(1 / 800, 1 / 800, 1 / 800)
  tag3d.position.set(...position)
  tag3d.rotation.set(...rotation)
  group.add(tag3d)
}

function createVideoMark(info) {
  const { imgUrl, wh, position, rotation } = info
  const video = document.createElement('video')
  video.muted = true
  video.src = imgUrl
  video.addEventListener('loadedmetadata', () => {
    video.play()
  })
  const plane = new THREE.PlaneGeometry(...wh)
  const material = new THREE.MeshBasicMaterial({
    map: new THREE.VideoTexture(video)
  })
  const mesh = new THREE.Mesh(plane, material)
  mesh.position.set(...position)
  mesh.rotation.set(...rotation)
  group.add(mesh)
}

function createLandMark(info) {
  const { imgUrl, wh, position, rotation, targetAttr } = info
  const geometry = new THREE.PlaneGeometry(...wh)
  const material = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load(imgUrl),
    side: THREE.DoubleSide,
    transparent: true //透明纹理 镂空只需要展示白色区域的内容
  })
  const mesh = new THREE.Mesh(geometry, material)
  mesh.position.set(...position)
  mesh.rotation.set(...rotation)
  // 添加名称 用于区分
  mesh.name = 'mark'
  // 绑定自定义属性 userData
  mesh.userData.attr = targetAttr
  group.add(mesh)
  // 加入dat.gui方便定位标记的定位位置
  // guiMove(mesh)
}

function bindClick() {
  const rayCaster = new THREE.Raycaster()
  const pointer = new THREE.Vector2()
  // 与3D的物体交互进行事件绑定
  window.addEventListener('click', (e) => {
    pointer.x = (e.clientX / window.innerWidth) * 2 - 1
    pointer.y = -(e.clientY / window.innerHeight) * 2 + 1

    rayCaster.setFromCamera(pointer, camera)
    const list = rayCaster.intersectObjects(scene.children)
    const obj = list.find(obj => obj.object.name === 'mark')
    if (obj) {
      const infoObj = sceneInfoObj[obj.object.userData.attr]
      setMaterialCube(infoObj)
    }
  })
}

const cubeObj = createCube()

// 首次渲染第一个场景内容
setMaterialCube(sceneInfoObj.one)
bindClick()